#include <iostream>

#include "objectmpi/objectmpi.h"
#include <mpi.h>

#include <unistd.h> // sleep()

using namespace std;

class dzialanie{
	public:
		int x;
		int y;
		int wynik;
};

class MySlave : public Slave{

	public:		
		void JobHandler(char* inputBuffer, int size){
			dzialanie* dzialanko = new dzialanie();
			memcpy(dzialanko, inputBuffer, size);
			
			dzialanko->wynik = dzialanko->x * dzialanko->y;
			
			printf("->Rank%d Operacja: %d * %d = ..\n", slaveId, dzialanko->x, dzialanko->y, dzialanko->wynik);
			printf("->Rank%d Operacja: Trwaja obliczenia...\n", slaveId);
			
			memcpy(inputBuffer, dzialanko, size);
			delete dzialanko;
		}
		
};

class MyMaster : public Master{
	
};



int main(int argc, char *argv[]){
	int pool_size, my_rank;

	MPI_Init(&argc, &argv);
	MPI_Comm_size(MPI_COMM_WORLD, &pool_size);
	MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
	
	printf("Initialized node: %d of %d\n", my_rank, pool_size);

	// poki co, testowe wyslanie 	
	if (my_rank==0){
		MPI_Request request;
		MPI_Status status;
		
		dzialanie* dzialanko = new dzialanie();
		int bufferSize = sizeof(dzialanie);
		char* buffer = new char[bufferSize];
		
		MyMaster* master = new MyMaster();
		master->SetParameters(buffer, bufferSize);
		
		for(int i=1; i<pool_size; i++){
			dzialanko->x = 5+i;
			dzialanko->y = 5+i;
			
			memcpy(buffer, dzialanko, bufferSize);
			
			master->SendJob(i, buffer, bufferSize);
		}
		
		for(int i=1; i<pool_size; i++){
			master->Receive(i, buffer, bufferSize);
			memcpy(dzialanko, buffer, bufferSize);
			
			printf("#Master: Otrzymano wynik: %d * %d = %d\n", dzialanko->x, dzialanko->y, dzialanko->wynik);
			master->SendTerminateSlave(i);
		}
	}
	
	// Slaves
	if (my_rank!=0){
		MySlave* mySlave = new MySlave();
		mySlave->SetParameters(my_rank, sizeof(dzialanie));
		mySlave->Start();
	}
		
	MPI_Finalize();
}
